package com.yc.cloud.openai.portal.service.impl;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yc.cloud.common.basic.dto.BaseQueryParam;
import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.common.oss.service.OssFileService;
import com.yc.cloud.openai.entity.GptDatasetCollection;
import com.yc.cloud.openai.mapper.GptDatasetCollectionMapper;
import com.yc.cloud.openai.portal.common.PortalErrorTips;
import com.yc.cloud.openai.portal.config.PathManager;
import com.yc.cloud.openai.portal.dao.GPTChatClient;
import com.yc.cloud.openai.portal.dto.gpt.GPTCreateDatasetCollectionDataDto;
import com.yc.cloud.openai.portal.dto.gpt.GptDatasetCollectionCreateDto;
import com.yc.cloud.openai.portal.dto.gpt.request.GptDatasetCollectionListParam;
import com.yc.cloud.openai.portal.dto.request.GptDatasetCollectionCreateRequest;
import com.yc.cloud.openai.portal.dto.request.GptDatasetCollectionDeleteRequest;
import com.yc.cloud.openai.portal.dto.response.GPTChatResponseResult;
import com.yc.cloud.openai.portal.enums.GPTChatProvider;
import com.yc.cloud.openai.portal.service.GptDatasetCollectionService;
import com.yc.cloud.openai.portal.service.GptDatasetService;
import com.yc.cloud.openai.portal.vo.gpt.GptDatasetCollectionVo;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.val;

/**
 * <p>
 * 知识库内容集合 服务实现类
 * </p>
 *
 * @author Yancy
 * @since 2025-01-08
 */
@Service
public class GptDatasetCollectionServiceImpl extends ServiceImpl<GptDatasetCollectionMapper, GptDatasetCollection>
        implements GptDatasetCollectionService {

    private final Map<GPTChatProvider, GPTChatClient> chatClients = new EnumMap<>(GPTChatProvider.class);
    private final OssFileService ossFileService;
    private final GptDatasetService gptDatasetService;
    private final PathManager pathManager;

    public GptDatasetCollectionServiceImpl(Map<String, GPTChatClient> chatClientMap, OssFileService ossFileService,
            GptDatasetService gptDatasetService, PathManager pathManager) {
        // 使用枚举的 value 作为键来初始化 Map
        chatClientMap.forEach((name, client) -> chatClients.put(GPTChatProvider.valueOf(name), client));
        this.ossFileService = ossFileService;
        this.gptDatasetService = gptDatasetService;
        this.pathManager = pathManager;
    }

    @Override
    public IPage<GptDatasetCollectionVo> list(BaseQueryParam queryParam, GptDatasetCollectionListParam param) {
        val query = new QueryWrapper<GptDatasetCollection>();
        IPage<GptDatasetCollection> page;
        if (param.getDatasetId() != null) {
            query.eq(GptDatasetCollection.DATASET_ID, param.getDatasetId());
        }
        // 排序
        if (StrUtil.isNotEmpty(queryParam.getSortBy())) {
            if (BaseQueryParam.ORDER_DESC.equals(queryParam.getOrder())) {
                query.orderByDesc(queryParam.getSortBy());
            } else if (BaseQueryParam.ORDER_ASC.equals(queryParam.getOrder())) {
                query.orderByAsc(queryParam.getSortBy());
            }
        }
        // 模糊查询
        // if (StrUtil.isNotEmpty(queryParam.getKeyword())) {
        // query.and(queryWrapper -> {

        // });
        // }
        // 分页
        if (queryParam.getPage()) {
            page = new Page<>(queryParam.getPageNum(), queryParam.getPageSize(), true);
        } else {
            page = new Page<>(queryParam.getPageNum(), baseMapper.selectCount(query), true);
        }
        val gptDatasetCollectionPage = baseMapper.selectPage(page, query);
        return gptDatasetCollectionPage.convert(this::convertVo);
    }

    @Override
    @SneakyThrows
    public GptDatasetCollectionVo create(GptDatasetCollectionCreateRequest param, MultipartFile file) {
        val client = chatClients.get(GPTChatProvider.fromKey(param.getProvider()));
        if (client == null) {
            throw new IllegalArgumentException("Invalid provider: " + param.getProvider());
        }
        // 获取知识库信息
        val gptDataset = gptDatasetService.getById(param.getDatasetId());
        if (gptDataset == null) {
            Asserts.fail(PortalErrorTips.DATASET_NOT_FOUND);
        }
        // 获取知识库服务ID
        val datasetId = gptDataset.getDatasetId();
        if (StrUtil.isEmpty(datasetId)) {
            Asserts.fail(PortalErrorTips.DATASET_ID_NOT_FOUND);
        }

        // 保存文件信息,
        val newFileName = java.net.URLEncoder.encode(param.getName(), "UTF-8") + "."
                + file.getOriginalFilename().split("\\.")[1];
        val dstFile = Paths.get(pathManager.getGPTFolder(), newFileName).toFile();
        FileUtil.writeFromStream(file.getInputStream(), dstFile);
        val fileId = ossFileService.generateFileId();
        val ossFile = ossFileService.buildOssFile(fileId, newFileName, dstFile.getPath());
        val saveOssFileFlag = ossFileService.save(ossFile);
        if (!saveOssFileFlag) {
            Asserts.fail(PortalErrorTips.SAVE_FILE_ERROR);
        }

        // 创建知识库内容
        val gptDatasetCollectionCreateDto = new GptDatasetCollectionCreateDto();
        // 创建调用服务的参数信息
        gptDatasetCollectionCreateDto.setFile(FileUtil.file(ossFile.getPath()));
        gptDatasetCollectionCreateDto.setDatasetId(datasetId);
        gptDatasetCollectionCreateDto.setTrainingType("chunk");
        // 请求接口服务
        GPTChatResponseResult<GPTCreateDatasetCollectionDataDto> createDatasetCollectionResponse = client
                .createDatasetCollection(gptDatasetCollectionCreateDto);
        if (createDatasetCollectionResponse.getCode() != GPTChatResponseResult.SUCCESS_CODE) {
            Asserts.fail(createDatasetCollectionResponse.getMessage());
        }
        val gptCreateDatasetCollectionDataDto = createDatasetCollectionResponse.getData();
        val collectionId = gptCreateDatasetCollectionDataDto.getCollectionId();
        if (StrUtil.isEmpty(collectionId)) {
            Asserts.fail(PortalErrorTips.CREATE_DATASET_COLLECTION_ERROR);
        }
        // 保存到数据库
        val gptdatasetcollection = new GptDatasetCollection();
        // copy一些字段值
        BeanUtils.copyProperties(gptDatasetCollectionCreateDto, gptdatasetcollection);
        gptdatasetcollection.setFileId(fileId);
        gptdatasetcollection.setCollectionId(collectionId);
        gptdatasetcollection.setDatasetId(param.getDatasetId());
        val saveFlag = save(gptdatasetcollection);
        return saveFlag ? convertVo(gptdatasetcollection) : null;
    }

    @Override
    public GptDatasetCollection get(Long id) {
        return getById(id);
    }

    @Override
    public boolean delete(Long id, GptDatasetCollectionDeleteRequest param) {
        val client = chatClients.get(GPTChatProvider.fromKey(param.getProvider()));
        if (client == null) {
            throw new IllegalArgumentException("Invalid provider: " + param.getProvider());
        }
        // 获取集合ID
        val gptDatasetCollection = getById(id);
        if (gptDatasetCollection == null) {
            Asserts.fail(PortalErrorTips.DATASET_COLLECTION_NOT_FOUND);
        }
        // 删除集合
        val deleteDatasetCollectionResponse = client.deleteDatasetCollection(gptDatasetCollection.getCollectionId());
        if (deleteDatasetCollectionResponse.getCode() != GPTChatResponseResult.SUCCESS_CODE) {
            Asserts.fail(deleteDatasetCollectionResponse.getMessage());
        }
        return removeById(id);
    }

    @Override
    public GptDatasetCollection update(Long id, GptDatasetCollection param) {
        val gptdatasetcollection = new GptDatasetCollection();
        BeanUtils.copyProperties(param, gptdatasetcollection);
        gptdatasetcollection.setId(id);
        val updateFlag = updateById(gptdatasetcollection);
        return updateFlag ? gptdatasetcollection : null;
    }

    @Override
    public GptDatasetCollectionVo convertVo(GptDatasetCollection gptdatasetcollection) {
        if (gptdatasetcollection == null) {
            return null;
        }
        val vo = new GptDatasetCollectionVo();
        BeanUtils.copyProperties(gptdatasetcollection, vo);
        // 获取文件信息
        val ossFile = ossFileService.getByFileId(gptdatasetcollection.getFileId());
        if (ossFile != null) {
            vo.setOssFile(ossFile);
        }
        return vo;
    }

    @Override
    public List<GptDatasetCollectionVo> convertVo(List<GptDatasetCollection> GptDatasetCollectionList) {
        if (CollUtil.isNotEmpty(GptDatasetCollectionList)) {
            return GptDatasetCollectionList.stream().map(this::convertVo).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

}
